package com.executor.gateway.filters.monitoring;

import com.executor.gateway.core.constant.GatewayConst;
import com.executor.gateway.model.bo.ApiConfigBo;
import com.executor.gateway.service.MetricsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.util.concurrent.CompletableFuture;

/**
 * 指标收集全局过滤器
 * 收集API调用的各种指标数据
 * 
 * @author miaoguoxin
 * @date 2024/01/01
 */
@Component
@Slf4j
public class MetricsCollectionGlobalFilter implements GlobalFilter, Ordered {

    @Autowired
    private MetricsService metricsService;

    private static final String START_TIME_ATTR = "startTime";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 记录请求开始时间
        exchange.getAttributes().put(START_TIME_ATTR, System.currentTimeMillis());
        
        ServerHttpRequest request = exchange.getRequest();
        Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
        ApiConfigBo apiConfig = exchange.getAttributeOrDefault(GatewayConst.CACHE_API_OBJECT_KEY, new ApiConfigBo());

        // 记录请求指标
        recordRequestMetrics(request, route, apiConfig);

        return chain.filter(exchange)
                .doOnSuccess(aVoid -> recordSuccessMetrics(exchange, route, apiConfig))
                .doOnError(throwable -> recordErrorMetrics(exchange, route, apiConfig, throwable))
                .doFinally(signalType -> recordResponseMetrics(exchange, route, apiConfig));
    }

    /**
     * 记录请求指标
     */
    private void recordRequestMetrics(ServerHttpRequest request, Route route, ApiConfigBo apiConfig) {
        try {
            CompletableFuture.runAsync(() -> {
                String serviceId = route != null ? route.getId() : "unknown";
                String method = request.getMethod().name();
                String path = request.getPath().value();
                String userAgent = request.getHeaders().getFirst("User-Agent");
                String clientIp = getClientIp(request);

                metricsService.recordRequest(serviceId, method, path, clientIp, userAgent, LocalDateTime.now());
                
                // 记录API级别指标
                if (apiConfig.getPatternUrl() != null) {
                    metricsService.incrementApiCounter(apiConfig.getPatternUrl(), "request");
                }
            });
        } catch (Exception e) {
            log.error("Error recording request metrics", e);
        }
    }

    /**
     * 记录成功响应指标
     */
    private void recordSuccessMetrics(ServerWebExchange exchange, Route route, ApiConfigBo apiConfig) {
        try {
            CompletableFuture.runAsync(() -> {
                Long startTime = exchange.getAttribute(START_TIME_ATTR);
                if (startTime != null) {
                    long responseTime = System.currentTimeMillis() - startTime;
                    String serviceId = route != null ? route.getId() : "unknown";
                    int statusCode = exchange.getResponse().getStatusCode() != null ? 
                            exchange.getResponse().getStatusCode().value() : 200;

                    metricsService.recordResponse(serviceId, statusCode, responseTime, LocalDateTime.now());
                    
                    // 记录API级别指标
                    if (apiConfig.getPatternUrl() != null) {
                        metricsService.incrementApiCounter(apiConfig.getPatternUrl(), "success");
                        metricsService.recordApiResponseTime(apiConfig.getPatternUrl(), responseTime);
                    }
                }
            });
        } catch (Exception e) {
            log.error("Error recording success metrics", e);
        }
    }

    /**
     * 记录错误指标
     */
    private void recordErrorMetrics(ServerWebExchange exchange, Route route, ApiConfigBo apiConfig, Throwable throwable) {
        try {
            CompletableFuture.runAsync(() -> {
                String serviceId = route != null ? route.getId() : "unknown";
                String errorType = throwable.getClass().getSimpleName();
                String errorMessage = throwable.getMessage();

                metricsService.recordError(serviceId, errorType, errorMessage, LocalDateTime.now());
                
                // 记录API级别错误指标
                if (apiConfig.getPatternUrl() != null) {
                    metricsService.incrementApiCounter(apiConfig.getPatternUrl(), "error");
                }
            });
        } catch (Exception e) {
            log.error("Error recording error metrics", e);
        }
    }

    /**
     * 记录响应指标（无论成功还是失败都会执行）
     */
    private void recordResponseMetrics(ServerWebExchange exchange, Route route, ApiConfigBo apiConfig) {
        try {
            CompletableFuture.runAsync(() -> {
                // 记录总体统计信息
                String serviceId = route != null ? route.getId() : "unknown";
                metricsService.updateServiceStatus(serviceId, LocalDateTime.now());
            });
        } catch (Exception e) {
            log.error("Error recording response metrics", e);
        }
    }

    /**
     * 获取客户端真实IP
     */
    private String getClientIp(ServerHttpRequest request) {
        String xForwardedFor = request.getHeaders().getFirst("X-Forwarded-For");
        if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
            return xForwardedFor.split(",")[0].trim();
        }
        
        String xRealIp = request.getHeaders().getFirst("X-Real-IP");
        if (xRealIp != null && !xRealIp.isEmpty()) {
            return xRealIp;
        }
        
        return request.getRemoteAddress() != null ? 
                request.getRemoteAddress().getAddress().getHostAddress() : "unknown";
    }

    @Override
    public int getOrder() {
        // 在认证和限流之后执行，确保能记录到完整的请求信息
        return Ordered.LOWEST_PRECEDENCE - 100;
    }
}